import requests
from robot.libraries.BuiltIn import BuiltIn
import robot
from robot.api import logger


def add_proxy_header(request_headers, proxy_headers):
    if request_headers is None:
        request_headers = {}
    if proxy_headers is not None:
        request_headers.update(proxy_headers)
    return request_headers


class HttpInterface(object):

    def http_proxy_post(self, url, proxy_headers, **params):
        """
        HTTP Post消息发送
        - :param url:
        - :param params: 可选，发送的清求参数，字典类型，如{'key': 'value'}，get消息 http://url/?key=value
        - :param data: 可选，HTTP消息Body里的内容，字典，列表，字节
        - :param json: 可选，HTTP消息Body里的内容，一个Json对像。
        - :param files: 可选，要发送的文件信息，比如{'name': ('filename',fileobj,'content_type')}.
        - param headers: 可选， header头，字典类型.
        - :param cookies: 可选， 字典或CookieJar类型，默认会自动给你处理，你也可以自己设置 .
        - :param auth: 可选，权益信息，tuple类型，包括 Basic/Digest/Custom HTTP Auth.
        - :param timeout: 可选，超时时间，单位秒，可以是tuple类型，（连接超时时间，获取数据超时时间）
        - :param allow_redirects: 是否允许跳转，默认是True.
        - :param proxies: 可选，代理信息 .
        - :param verify: 可选，是否检证TLS证书，如果是字符串，则表示使用TLS证书的路径，默认为True
        - :param stream: (optional) if ``False``, the response content will be immediately downloaded.
        - :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair.
        - *return*: 以encoding解析返回内容，会自动根据响应头部的字符编码进行解码
        注：
        - 获取HTTP消息响应码：${_HTTP_RESPONSE.status_code}
        - 获取响应消息的Header头中的Connection值：${_HTTP_RESPONSE.headers['Connection']}
        """

        request_cookie, request_headers = self._get_http_cookie_and_headers(params.pop('cookies', None),
                                                                            params.pop('headers', None))
        request_headers = add_proxy_header(request_headers, proxy_headers)
        logger.debug("request header {}".format(request_headers))
        result = requests.post(url, cookies=request_cookie, headers=request_headers, **params)
        self._save_http_cookie_and_headers(result)
        return result.text

    def http_post(self, url, **params):
        self.http_proxy_post(url, None, params)

    def _get_http_cookie_and_headers(self, request_cookie, request_headers):
        """
        获取cookie和header，以元组形式返回
        :param request_cookie: 字典或CookieJar类型
        :param request_headers: header头，字典类型.
        """
        save_cookie = BuiltIn().get_variable_value('${_HTTP_COOKIE}')
        if save_cookie and not request_cookie:
            # 如果有保存cookie，并且入参没有cookie，则使用保存的cookie
            request_cookie = BuiltIn().get_variable_value('${_HTTP_COOKIE}')

        if hasattr(self, '_http_headers_save'):
            for header_name in self._http_headers_save:
                header_value = BuiltIn().get_variable_value('${_HTTP_HEADER_%s}' % header_name)
                if header_value:
                    if not request_headers:
                        # 如果有保存header, 并且入参没有headers, 则直接header赋值
                        request_headers = {header_name: header_value}
                    elif header_name not in request_headers:
                        # 如果有保存的header，入参有headers, 但是没有保存的header名字，则增加header_name
                        request_headers[header_name] = header_value

        # 入参params后面自己更新
        return request_cookie, request_headers

    def _save_http_cookie_and_headers(self, result):
        """
        保存HTTP消息
        :param result: 响应消息
        :return: None
        """
        try:
            BuiltIn().set_test_variable('${_HTTP_RESPONSE}', result)
            if len(result.cookies) > 0:
                cookie_jar = result.cookies
                cookie = requests.utils.dict_from_cookiejar(cookie_jar)
                BuiltIn().set_test_variable('${_HTTP_COOKIE}', cookie)

            if hasattr(self, '_http_headers_save'):
                for header_name in self._http_headers_save:
                    if header_name in result.headers:
                        BuiltIn().set_test_variable('${_HTTP_HEADER_%s}' % header_name, result.headers[header_name])
        except robot.errors.DataError as e:
            logger.warn("Save the http cookie and headers failed. " + str(e))
            # 如果test_variable设置不了，去设置suite变量，确保这个关键字在suite级别可用
            BuiltIn().set_suite_variable('${_HTTP_RESPONSE}', result)
        except Exception as e:
            # 如打印错误日志，不影响流程
            logger.warn("Save the http cookie and headers failed. " + str(e))

http_interface_obj = HttpInterface()